package com.fred.colorpicker

import android.annotation.SuppressLint
import android.content.Context
import android.content.SharedPreferences
import android.os.Build
import android.util.AttributeSet
import android.view.MotionEvent
import android.view.ViewGroup
import android.widget.FrameLayout
import androidx.annotation.RequiresApi
import com.fred.colorpicker.listener.ColorWheelListener
import com.fred.colorpicker.indicator.ColorWheelIndicator

class ColorWheelView:FrameLayout {

    private val minInterval = 1000/60
    private var lastPassedEventTime = 0L

    private val colorPalette by lazy {
        ColorWheelPalette(context)
    }
    var oneIndicator: ColorWheelIndicator? = null
    var twoIndicator: ColorWheelIndicator? = null

    var onlyUpdateOnTouchEventUp = false
    var colorWheelListener: ColorWheelListener?=null


    constructor(context: Context) : super(context){
        init()
    }
    constructor(context: Context, attrs: AttributeSet?) : super(context, attrs){
        init()
    }
    constructor(context: Context, attrs: AttributeSet?, defStyleAttr: Int) : super(
            context,
            attrs,
            defStyleAttr
    ){
        init()
    }

    @RequiresApi(Build.VERSION_CODES.LOLLIPOP)
    constructor(
            context: Context,
            attrs: AttributeSet?,
            defStyleAttr: Int,
            defStyleRes: Int
    ) : super(context, attrs, defStyleAttr, defStyleRes){
        init()
    }

    override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec)
        val width = MeasureSpec.getSize(widthMeasureSpec)
        val widthMode = MeasureSpec.getMode(widthMeasureSpec)
        val height = MeasureSpec.getSize(heightMeasureSpec)
        val heightMode = MeasureSpec.getMode(heightMeasureSpec)
        val realWidth = if (widthMode == MeasureSpec.EXACTLY){
            width
        }else{
            colorPalette.measuredWidth
        }
        val realHeight = if (heightMode == MeasureSpec.EXACTLY){
            height
        }else{
            colorPalette.measuredHeight
        }
        setMeasuredDimension(realWidth, realHeight)
    }

    @SuppressLint("ClickableViewAccessibility")
    override fun onTouchEvent(event: MotionEvent?): Boolean {
        when(event?.actionMasked?:-1){
            MotionEvent.ACTION_DOWN->{
                event?.apply {
                    changeSelect(this.x, this.y)
                    update(this.x, this.y, false)
                }
                return true
            }
            MotionEvent.ACTION_MOVE -> {
                val current = System.currentTimeMillis()
                if (current - lastPassedEventTime > minInterval) {
                    lastPassedEventTime = current
                    event?.apply { update(this.x, this.y, false) }
                    return true
                }
            }
            MotionEvent.ACTION_UP -> {
                event?.apply { update(this.x, this.y, true) }
                return true
            }
        }
        return super.onTouchEvent(event)
    }

    override fun onSizeChanged(w: Int, h: Int, oldw: Int, oldh: Int) {
        super.onSizeChanged(w, h, oldw, oldh)
        oneIndicator?.initColorWheelPosition(w, h)
        twoIndicator?.initColorWheelPosition(w, h)
    }

    fun setSelector(one: ColorWheelIndicator, two: ColorWheelIndicator? = null){
        val layoutParams = LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT,
                ViewGroup.LayoutParams.WRAP_CONTENT)
        val colorWidth = colorPalette.width
        val colorHeight = colorPalette.height
        if (oneIndicator == null){
            oneIndicator = one
            oneIndicator?.isSelected = true
            oneIndicator?.layoutParams?.width = colorWidth
            oneIndicator?.layoutParams?.height = colorHeight
            addView(oneIndicator, layoutParams)
        }
        if (twoIndicator == null && two != null){
            twoIndicator = two
            twoIndicator?.layoutParams?.width = colorWidth
            twoIndicator?.layoutParams?.height = colorHeight
            addView(twoIndicator, layoutParams)
        }
    }


    private fun init(){
        val layoutParams = LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT,
                ViewGroup.LayoutParams.WRAP_CONTENT)
        addView(colorPalette, layoutParams)
    }

    private fun changeSelect(x: Float, y: Float){
        if (oneIndicator?.isInside(x,y) == true){
            if (oneIndicator?.isSelected != true){
                twoIndicator?.isSelected = false
                oneIndicator?.apply {
                    isSelected = true
                    colorWheelListener?.onSelectorChange(this,twoIndicator)
                }
            }
        }else if (twoIndicator?.isInside(x,y) == true){
            if (twoIndicator?.isSelected != true){
                oneIndicator?.isSelected = false
                twoIndicator?.apply {
                    isSelected = true
                    colorWheelListener?.onSelectorChange(oneIndicator,this)
                }
            }
        }
    }

    private fun update(x: Float, y: Float, isTouchUp: Boolean){
        val point = colorPalette.calculateEffective(x, y)
        if (oneIndicator?.isSelected == true){
            if (twoIndicator?.isInside(point.x,point.y) == true){
                return
            }
        }else if (twoIndicator?.isSelected == true){
            if (oneIndicator?.isInside(point.x,point.y) == true){
                return
            }
        }
        if (!onlyUpdateOnTouchEventUp || isTouchUp){
            val color = colorPalette.getColor(point)
            val grad = colorPalette.getGrad(point)
            colorWheelListener?.onSelectColor(color, grad[1], grad[2])
        }
        if (oneIndicator?.isSelected == true){
            oneIndicator?.setCurrentPoint(point)
        }else if (twoIndicator?.isSelected == true){
            twoIndicator?.setCurrentPoint(point)
        }
        if (isTouchUp){
            val settings: SharedPreferences = context.getSharedPreferences("colorPicker", Context.MODE_PRIVATE)
            val edit = settings.edit()
            if (oneIndicator?.isSelected == true){
                oneIndicator?.setColorWheelConfig(point.x/width,point.y/height)
            }else if (twoIndicator?.isSelected == true){
                twoIndicator?.setColorWheelConfig(point.x/width,point.y/height)
            }
            edit.apply()
        }
    }



}